package com.gandong8.trace.tool.service.impl;

import com.gandong8.trace.tool.domain.ResponseData;
import com.gandong8.trace.tool.domain.RequestData;
import com.gandong8.trace.tool.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;


@Slf4j
@Service("restTemplateService")
public class RestTemplateService extends HttpPublicService {


    @Override
    ResponseData doBoth(RequestData requestData)  {
        HttpHeaders headers = new HttpHeaders();
        if(requestData.getHeaders() != null) {
            requestData.getHeaders().forEach(headers::add);
        }
        HttpEntity<Object> entity;
        if(requestData.getPostJson() != null) {
            headers.setContentType(MediaType.APPLICATION_JSON);
            entity = new HttpEntity<>(requestData.getPostJson(), headers);
        } else if(requestData.getPostParams() != null) {
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            entity = new HttpEntity<>(requestData.getPostParams(), headers);
        } else {
            entity = new HttpEntity<>(null, headers);
        }
        RestTemplate restTemplate = new RestTemplate(getRequestFactory(requestData));
        restTemplate.setMessageConverters(getMessageConverters());
        ResponseEntity<String> exchange = restTemplate.exchange(requestData.getUrl(), requestData.isGet() ?HttpMethod.GET:HttpMethod.POST, entity, String.class);
        ResponseData responseData = new ResponseData();
        responseData.setData(exchange.getBody());
        responseData.setHttpStatusCode(exchange.getStatusCodeValue());
        return responseData;
    }

    private ClientHttpRequestFactory getRequestFactory(RequestData requestData) {
        CloseableHttpClient httpClient = requestData.isHttps() ? (CloseableHttpClient) HttpUtil.getClientNoSSL() : HttpClients.createDefault();
        HttpComponentsClientHttpRequestFactory requestFactory =
                new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        requestFactory.setConnectTimeout(requestData.getConnectTimeout());
        requestFactory.setReadTimeout(requestData.getSocketTimeout());
        return requestFactory;
    }

    private List<HttpMessageConverter<?>>  getMessageConverters() {
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        messageConverters.add(new ByteArrayHttpMessageConverter());
        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
        messageConverters.add(stringHttpMessageConverter);
        messageConverters.add(new ResourceHttpMessageConverter());
        messageConverters.add(new SourceHttpMessageConverter());
        messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        return messageConverters;
    }


}
